package com.sghd.candy.module.fight.service;

import com.sghd.candy.module.box.manager.BoxKeysConfig;
import com.sghd.candy.module.box.service.BoxService;
import com.sghd.candy.module.element.manager.ElementConfig;
import com.sghd.candy.module.element.service.ElementConfigService;
import com.sghd.candy.module.fight.FightConfig;
import com.sghd.candy.module.fight.manager.*;
import com.sghd.candy.module.player.manager.Player;
import com.sghd.common.ramcache.aop.AutoLocked;
import com.sghd.common.ramcache.aop.IsLocked;
import com.sghd.common.socket.session.Session;
import com.sghd.common.socket.session.SessionManager;
import com.sghd.common.utils.codec.CryptUtils;
import com.sghd.pojo.candy.box.enums.ScopeType;
import com.sghd.pojo.candy.fight.enums.BattleResult;
import com.sghd.pojo.candy.fight.enums.Grade;
import com.sghd.pojo.candy.fight.vo.ServerVo;
import com.sghd.pojo.fight.game.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import static com.sghd.candy.module.fight.FightConfig.SessionKeys.KEY_FIGHT_SERVER_ID;

/**
 * @author Allen
 * @date 2018/12/03
 */
@Service
public class FightService {
    private static final Logger logger = LoggerFactory.getLogger(FightService.class);
    private final String CRYPT_KEY = "bbb";
    @Autowired
    private FightManager fightManager;
    @Autowired
    private LevelConfigManager levelConfigManager;
    @Autowired
    private LevelInfoManager levelInfoManager;
    @Autowired
    private SessionManager sessionManager;
    @Autowired
    private ElementConfigService elementConfigService;
    @Autowired
    private BoxService boxService;

    public ServerVo getFightServer(Player player) {
        // 获取玩家战斗信息
        FightInfo fightInfo = fightManager.load(player.getPlayerId());
        ServerConfig fightServer = null;
        boolean isReconn = false;
        if (fightInfo.getServerId() == -1) {
            fightServer = fightManager.getAvailableServer();
        } else {
            // 在战斗服
            if (fightInfo.getRoomType() == RoomType.PVP) {
                // 重连
                fightServer = fightManager.load(fightInfo.getServerId());
                isReconn = true;
            } else if (fightInfo.getRoomType() == RoomType.PVE) {
                fightServer = fightManager.getAvailableServer();
            }
        }

        if (fightServer == null) {
            return ServerVo.maintain();
        }

        Session session = sessionManager.getSession(player.getPlayerId());
        session.getContext().put(KEY_FIGHT_SERVER_ID, fightServer.getServerId());

        int timestamp = (int) (System.currentTimeMillis() / 1000);
        String token = CryptUtils.generateToken(CRYPT_KEY, player.getPlayerId(), timestamp);

        ServerVo serverVo = ServerVo.valueOf(fightServer.getServerIp(), fightServer.getPort(), token, timestamp);
        serverVo.setReConn(isReconn);

        return serverVo;
    }

    public FightInfo load(Player player) {
        return fightManager.load(player.getPlayerId());
    }
    /*public Result<String> getServer(Player player, RoomType roomType) {
        // 获取玩家战斗信息
        FightInfo fightInfo = fightManager.load(player.getPlayerId());
        // 是否符合要求
        if (roomType == RoomType.PVP) {
            LevelInfo levelInfo = levelInfoManager.getLevelInfo(player.getPlayerId());
            if (levelInfo.getBigLevelId()<= 1) {
                return Result.valueOf(-1, "请完成PVE第一章节!");
            }
        }

        FightServer fightServer = null;
        if (fightInfo.getServerId() == -1) {
            fightServer = fightManager.getAvailableServer();
        } else {
            // 在战斗服
            if (fightInfo.getRoomType() == RoomType.PVP) {
                // 重连
                fightServer = fightManager.load(fightInfo.getServerId());
            } else if (fightInfo.getRoomType() == RoomType.PVE) {
                fightServer = fightManager.getAvailableServer();
            }
        }

        if (fightServer == null) {
            return Result.valueOf(-1,"服务器维护中，无法进入，请联系客服。");
        }

        Session session = sessionManager.getSession(player.getPlayerId());
        session.getContext().put(FightConfig.SessionKeys.KEY_SERVER_ID, fightServer.getServerId());
        return Result.valueOf(fightServer.getServerIp() + ":" + fightServer.getPort());
    }*/

    public void connect(Player player, RoomType roomType) {
        FightInfo fightInfo = fightManager.load(player.getPlayerId());

        Session session = sessionManager.getSession(player.getPlayerId());
        fightManager.connect(fightInfo, roomType, (Integer) session.getContext().get(KEY_FIGHT_SERVER_ID));
    }

    public void disConnect(Player player) {
        if(player == null){
            return;
        }
        FightInfo fightInfo = fightManager.load(player.getPlayerId());
        fightManager.disConnect(fightInfo);
    }

    @AutoLocked
    public void pvpWinSettlement(@IsLocked Player player, int initBlood, int leftBlood, long getMoney, SettleVo settleVo) {
        DropVo dropVo = DropVo.valueOf();
        long winMoney = 100 * leftBlood / initBlood / 10 * 10 + leftBlood * 20;
        winMoney += getMoney;
        dropVo.setDropMoney(winMoney);
        ElementConfig elementConfig = elementConfigService.getDropElement(BattleResult.WIN);
        BoxKeysConfig boxKeysConfig = boxService.getDropBoxKey(ScopeType.PVP, BattleResult.WIN);
        if (elementConfig != null) {
            dropVo.setDropElement(1);
        }
        if (boxKeysConfig != null) {
            dropVo.getBoxKeys().put(boxKeysConfig.getKeyId(), 1);
        }
        if(null != player){
            settleVo.getDropVoMap().put(player.getPlayerId(), dropVo);
            fightManager.pvpSettlement(fightManager.load(player.getPlayerId()), BattleResult.WIN);
        }
    }

    @AutoLocked
    public void pvpLoseSettlement(@IsLocked Player player, long getMoney, SettleVo settleVo) {
        DropVo dropVo = DropVo.valueOf();
        long loseMoney = 10 + getMoney;
        dropVo.setDropMoney(loseMoney);
        ElementConfig elementConfig = elementConfigService.getDropElement(BattleResult.LOSE);
        BoxKeysConfig boxKeysConfig = boxService.getDropBoxKey(ScopeType.PVP, BattleResult.LOSE);
        if (elementConfig != null) {
            dropVo.setDropElement(1);
        }
        if (boxKeysConfig != null) {
            dropVo.getBoxKeys().put(boxKeysConfig.getKeyId(), 1);
        }
        if (null != player) {
            settleVo.getDropVoMap().put(player.getPlayerId(), dropVo);
            fightManager.pvpSettlement(fightManager.load(player.getPlayerId()), BattleResult.LOSE);
        }
    }

    @AutoLocked
    public void pveSettlement(@IsLocked Player player, long getMoney, int leftBlood, SettleVo settleVo) {
        DropVo dropVo = DropVo.valueOf();
        LevelId levelId = LevelId.valueOf(settleVo.getLevel().getBigLevelId(), settleVo.getLevel().getLevelId());
        LevelConfig levelConfig = levelConfigManager.getLevelConfig(levelId);

        if (levelConfig == null) {
            if (logger.isDebugEnabled()) {
                logger.debug("关卡[{}]不存在", levelId.toString());
            }
            return;
        }

        // 非特殊关卡，血量判断
        if (levelConfig.getIsSpecial() != 1) {
            if (leftBlood <= 0) {
                settleVo.setWinId(-1);
                if (logger.isDebugEnabled()) {
                    logger.debug("玩家ID[{}]，挑战关卡[{}]失败。", player.getPlayerId(), levelId.getBigLevelId() + "-" + levelId.getLevelId());
                }
                return;
            }

            //星级判断并保存
            if (leftBlood >= levelConfig.getGradeThree().get(FightConfig.GRADE_KEY_LEFTBLOOD)) {
                settleVo.setGrade(Grade.THREE);
            } else if (leftBlood >= levelConfig.getGradeTwo().get(FightConfig.GRADE_KEY_LEFTBLOOD)) {
                settleVo.setGrade(Grade.TWO);
            } else {
                settleVo.setGrade(Grade.ONE);
            }
        } else {
            if (settleVo.getReason() == ExitReason.OFFLINE) {
                if (logger.isDebugEnabled()) {
                    logger.debug("特殊关卡，玩家ID[{}]，掉线，不结算。", player.getPlayerId());
                }
                return;
            }
            settleVo.setGrade(Grade.THREE);
        }

        LevelInfo levelInfo = levelInfoManager.getLevelInfo(player.getPlayerId());
        if (levelInfo.getBigLevelId() == -1 && levelInfo.getLevelId() == -1) {
            if (logger.isDebugEnabled()) {
                logger.debug("玩家ID[{}]，已完成全部挑战。", player.getPlayerId());
            }
            return;
        }

        if (levelId.getLevelStr().compareTo(levelInfo.getLevelStr()) > 0) {
            if (logger.isDebugEnabled()) {
                logger.debug("玩家ID[{}]，当前关卡[{}]，挑战关卡[{}]，已越级。",
                        player.getPlayerId(),
                        levelInfo.getBigLevelId() + "-" + levelInfo.getLevelId(),
                        levelId.getBigLevelId() + "-" + levelId.getLevelId());
            }
            return;
        }

        //金币掉落
        dropVo.setDropMoney(levelConfig.getMoney() + getMoney);

        // 判断是否重复
        if (!levelInfo.getLevelGrade().containsKey(levelId.getBigLevelId() + "-" + levelId.getLevelId())) {
            //五行掉落
            dropVo.setDropElement(levelConfig.getElementDrop());

            //宝箱钥匙落
            levelConfig.getBoxKeyDrop().forEach((k, v) -> {
                double random = Math.random();
                if (random <= v) {
                    dropVo.getBoxKeys().put(k, 1);
                }
            });
            //保存进度
            LevelId nextLevelId = levelConfigManager.getNextLevel(levelConfig);
            levelInfoManager.update(levelInfo, nextLevelId);
        } else {
            if (logger.isDebugEnabled()) {
                logger.debug("玩家ID[{}]，挑战关卡[{}]，重复挑战。", player.getPlayerId(), levelId.getBigLevelId() + "-" + levelId.getLevelId());
            }
        }

        settleVo.getDropVoMap().put(player.getPlayerId(), dropVo);

        //保存评分
        int addGrade = levelInfoManager.update(levelInfo, levelId, settleVo.getGrade());

        FightInfo fightInfo = fightManager.load(player.getPlayerId());
        fightManager.pveSettlement(fightInfo, addGrade);
    }

    public int levelSelect(Player player, LevelVo levelVo) {
        LevelId levelId = LevelId.valueOf(levelVo.getBigLevelId(), levelVo.getLevelId());
        LevelInfo levelInfo = levelInfoManager.getLevelInfo(player.getPlayerId());
        if (levelInfo.getBigLevelId() == -1 && levelInfo.getLevelId() == -1) {
            if (logger.isDebugEnabled()) {
                logger.debug("玩家ID[{}]，已完成全部挑战。", player.getPlayerId());
            }
            return 0;
        }
        if (levelId.getLevelStr().compareTo(levelInfo.getLevelStr()) > 0) {
            if (logger.isDebugEnabled()) {
                logger.debug("玩家ID[{}]，当前关卡[{}]，挑战关卡[{}]，已越级。",
                        player.getPlayerId(),
                        levelInfo.getBigLevelId() + "-" + levelInfo.getLevelId(),
                        levelId.getBigLevelId() + "-" + levelId.getLevelId());
            }
            return 0;
        }
        return 1;
    }
}
